import { _decorator, Camera, Canvas, Component, director, EventMouse, instantiate, Node, Prefab, TiledLayer, TiledMap, v2, v3, Vec2, Vec3, EventTarget, UITransform } from 'cc';
import { AStarNode, AStarPathfinder } from './AStarNode';
import { AStarWay } from './AStarWay';
import { pathNode } from './pathNode';
// import { AStarWay } from './AStarWay';
const { ccclass, property } = _decorator;

const eventTarget = new EventTarget();

@ccclass('game')
export class game extends Component {
    @property(Node)
    map: Node;
    @property(Node)
    pathNode: Node;

    @property(Prefab)
    playerPrefab: Prefab;
    @property(Prefab)
    pathPrefab: Prefab;
    @property(Prefab)
    realPathPrefab: Prefab;
    @property(Prefab)
    targetPrefab: Prefab;

    private tiledMap: TiledMap
    private bgLayer: TiledLayer;
    private objectLayer: TiledLayer;
    private player: Node;
    private target: Node;

    // 移动目标点
    private targetPoint: Vec2;

    private aStarPathfinder: AStarPathfinder;
    private aStarWay: AStarWay;
    // 开始函数
    start() {
        this.tiledMap = this.map.getComponent(TiledMap);

        // 获取背景层
        this.bgLayer = this.map.getChildByName('bgLayer').getComponent(TiledLayer);
        // 获取对象层
        this.objectLayer = this.map.getChildByName('objectLayer').getComponent(TiledLayer);

        let playerCoord = v2(0, 0);
        let pos = this.tileToWorldCoordinates2(v3(6, 6));
        this.player = instantiate(this.playerPrefab);
        this.player.parent = this.node;
        this.player.setWorldPosition(pos.x, pos.y, 0)

        this.map.on(Node.EventType.MOUSE_DOWN, this.mapMouseDown, this);
    }

    update(deltaTime: number) {

    }

    worldToTileCoordinates(position: Vec3): Vec3 {
        let localPos = v3();
        Vec3.subtract(localPos, v3(position.x, position.y), this.map.worldPosition);
        let mapSize = this.tiledMap.getMapSize();
        let tileSize = this.tiledMap.getTileSize();
        let x: number = Math.floor(mapSize.x / 2 + localPos.x / tileSize.width);
        let y: number = Math.floor(mapSize.y / 2 - localPos.y / tileSize.height);
        return new Vec3(x, y, 0);

    }

    tileToWorldCoordinates2(tileCoord: Vec3): Vec3 {
        let mapSize = this.tiledMap.getMapSize();
        let tileSize = this.tiledMap.getTileSize();
        let basePos = this.map.worldPosition;
        let x: number = basePos.x + (tileCoord.x - mapSize.x / 2 + 0.5) * tileSize.width;
        let y: number = basePos.y + (mapSize.y / 2 - tileCoord.y - 0.5) * tileSize.height;
        return new Vec3(x, y, 0);
    }

    //1可以走2不可以走
    initMapData(): number[][] {
        let mapData: number[][] = new Array(this.tiledMap.getMapSize().y);
        for (let i = 0; i < this.tiledMap.getMapSize().y; i++) {
            mapData[i] = new Array(this.tiledMap.getMapSize().x).fill(0);
        }
        for (let i = 0; i < this.tiledMap.getMapSize().y; i++) {
            for (let j = 0; j < this.tiledMap.getMapSize().x; j++) {
                if (this.objectLayer.getTileGIDAt(j, i) > 0) {
                    mapData[i][j] = 1;
                }
            }
        }
        return mapData;
    }

    pathArray: Node[] = new Array<Node>();
    r1: Node[] = new Array<Node>();
    mapMouseDown(event: EventMouse) {
        // 获取鼠标屏幕坐标
        const mousePos = event.getLocation();
        // 获取主摄像机
        const mainCamera = director.getScene()!.getComponentInChildren(Camera)!;
        var target = mainCamera.screenToWorld(v3(mousePos.x, mousePos.y));

        var tileCoordinates = this.worldToTileCoordinates(v3(target.x, target.y));  //目标点位转换为瓦片坐标
        var targetPath = this.tileToWorldCoordinates2(tileCoordinates);  //瓦片坐标中心世界坐标

        this.targetPoint = v2(tileCoordinates.x, tileCoordinates.y);
        if (this.target == undefined) {
            this.target = instantiate(this.targetPrefab);
            this.target.parent = this.pathNode;
        }

        this.target.setWorldPosition(targetPath.x, targetPath.y, 0)


        this.aStarPathfinder = new AStarPathfinder(this.initMapData(), eventTarget);


        eventTarget.on('realPath', (s: AStarNode) => {
            // this.pathArray.forEach(element => {
            //     element.destroy();
            // })
            let path = instantiate(this.realPathPrefab);
            path.parent = this.pathNode;
            path.setWorldPosition(this.tileToWorldCoordinates2(v3(s.x, s.y, 0)));
        }, this);

        eventTarget.on('path', (s: AStarNode) => {
            let path = instantiate(this.pathPrefab);
            path.parent = this.pathNode;
            path.setWorldPosition(this.tileToWorldCoordinates2(v3(s.x, s.y, 0)));
            this.pathArray.push(path);
        }, this);

        eventTarget.on('r0', (s: AStarNode) => {
            let path = instantiate(this.realPathPrefab);
            path.parent = this.pathNode;
            path.setWorldPosition(this.tileToWorldCoordinates2(v3(s.x, s.y, 0)));
        }, this);

        eventTarget.on('r1', (s: AStarNode) => {
            // ss.forEach(s => {
                let path = instantiate(this.pathPrefab);
                path.parent = this.pathNode;
                path.setWorldPosition(this.tileToWorldCoordinates2(v3(s.x, s.y, 0)));
                var pathNodeCom = path.getComponent(pathNode)
                pathNodeCom.F.string = s.f.toString();
                pathNodeCom.G.string = s.g.toString();
                pathNodeCom.H.string = s.h.toString();
                this.r1.push(path);
            // })
        }, this);

         eventTarget.on('result', (ss: AStarNode[]) => {
             ss.forEach(s => {
                let path = instantiate(this.playerPrefab);
                path.parent = this.pathNode;
                path.setWorldPosition(this.tileToWorldCoordinates2(v3(s.x, s.y, 0)));
               
                this.r1.push(path);
             })
        }, this);
    }

    next() {
        var start = this.worldToTileCoordinates(this.player.worldPosition);
        this.aStarPathfinder.findPath(start.x,start.y,this.targetPoint.x,this.targetPoint.y);
        // this.aStarWay = new AStarWay(v2(start.x, start.y), this.targetPoint, this.initMapData(), eventTarget);
        // this.aStarWay.getPath();
        // let oldPath = instantiate(this.realPathPrefab);
        // oldPath.parent = this.pathNode;
        // oldPath.setWorldPosition(this.tileToWorldCoordinates2(v3(this.aStarWay.start.x,this.aStarWay.start.y,0)));

        // let needCalPaths = this.aStarWay.getNeedCalPath();

        // needCalPaths.forEach(element => {
        //     let needCalPathItem = instantiate(this.pathPrefab);
        //     needCalPathItem.parent = this.pathNode;
        //     var wordPos = this.tileToWorldCoordinates2(v3(element.x,element.y,0))
        //     needCalPathItem.setWorldPosition(wordPos);
        // });

        // this.aStarWay.getBest();
    }


}



